/*
 * AdjacencyList.h
 *
 *  Created on: 2012-04-04
 *      Author: tony
 */
#include <iostream>

#ifndef ADJACENCYLIST_H_
#define ADJACENCYLIST_H_

#include <vector>
#include "Vertex.h"
#include "DoublyLinkedList.h"


namespace graph {

class AdjacencyList {
public:
	AdjacencyList();
	AdjacencyList(const int n);
	void addEdge(const int i, const int j, const float w);
	void removeEdge(const int i, const int j);
	virtual ~AdjacencyList();
	std::vector<Vertex*>* getListOfVertices();
	friend std::ostream& operator <<(std::ostream& out, const AdjacencyList& g) {
		AdjListNode* p = g.first;
		while (p != NULL){
			out << *p << std::endl;
			p = p->getNextVertex();
		}
		return out;
	}
private:
	/*
	 * Data member:
	 */
	class AdjListNode;
	AdjListNode* first;

	/*
	 * Private find method
	 */
	AdjListNode* findNode(const int s) const {
		for ( AdjListNode* p=first; p!=NULL; p=p->getNextVertex() )
			if (p->getVertex() == s )
				return p;
		return NULL;
	}



	class AdjListNode{
	public:
		AdjListNode(const int s):sourceVertex(s) {
			std::cout << "      AdjListNode constructor - no params" << std::endl;
			data = NULL;
		}
		AdjListNode(const int s, DoublyLinkedList* d, AdjListNode* n): sourceVertex(s), data(d), nextVertex(n){
			std::cout << "      AdjListNode constructor - 2 args" << std::endl;
		}
		void addEdge(const int i, const int j, const float w){
			std::cout << "       AdjListNode addEdge - " << i << " " << j << " " << w << std::endl;
			if (data == NULL)
				data = new DoublyLinkedList();
			data->addEdge( i, j, w);
		}
		void removeEdge(const int i, const int j){
			std::cout << "       AdjListNode removeEdge - " << i << " " << j << std::endl;
			if (data == NULL)
				return;
			data->removeEdge( i, j );
		}
		virtual ~AdjListNode(){
			std::cout << "      AdjListNode destructor" << std::endl;
			if (data != NULL)
				delete data;
		}
		// getters, setters
		int getVertex()const { return sourceVertex; }
		AdjListNode* getNextVertex()const { return nextVertex; }
		DoublyLinkedList* getData()const { return data; }
		// insertion operator
		friend std::ostream& operator <<(std::ostream& out, const AdjListNode& n) {
			out << n.sourceVertex << ": ";
			if (n.data != NULL)
				out << *(n.data);
			out << std::endl;
			return out;
		}

	private:
		const int sourceVertex;
		DoublyLinkedList* data;
		AdjListNode*      nextVertex;
	};

};

} /* namespace graph */
#endif /* ADJACENCYLIST_H_ */
